from django.db import models
import logging


class Post(models.Model):
    
    STATUS_CHOICES = (
        ('Published', 'Published'),
        ('Draft', 'Draft')
    )
    title = models.CharField(max_length=100, unique=True)
    summary = models.TextField()
    content = models.TextField()
    publish_datetime = models.DateTimeField(auto_now_add=True)
    update_datetime = models.DateTimeField(auto_now=True)
    status = models.CharField(max_length=9, choices=STATUS_CHOICES, default='Published')
    visible = models.BooleanField(default=True)
    tag = models.ManyToManyField('Tag', related_name='post_tag', null=True, blank=True)
    category = models.ForeignKey('Category', null=True, blank=True)
    view_count = models.IntegerField(default=0)

    @property
    def post_tag(self):
        return ', '.join([tag.content for tag in self.tag.all()])

    @property
    def post_tag_list(self):
        return [tag.content for tag in self.tag.all()]

    class Meta:
        ordering = ['-publish_datetime']

    def save(self, *args, **kwargs):
        if self.status == 'Draft' and self.title.find('[draft]') < 0:
            self.title = '%s [draft]' % self.title
        else:
            self.title = self.title.replace(' [draft]', '')
        super(Post, self).save(*args, **kwargs)

    def __unicode__(self):
        return self.title


class Tag(models.Model):
    
    content = models.CharField(unique=True, max_length=20)

    @property
    def post_count(self):
        return self.post_tag.count()

    def save(self, *args, **kwargs):
        if self.content.find(',') >= 0:
            contents = self.content.split(',')
            for content in contents:
                if not Tag.objects.filter(content=content).exists():
                    self.content = content
                    if Tag.objects.filter(pk=self.id).exists():
                        self.id += 1
                    super(Tag, self).save(*args, **kwargs)
        else:
            super(Tag, self).save(*args, **kwargs)

    def __unicode__(self):
        return self.content


class CategoryManager(models.Manager):
    @staticmethod
    def generate_unordered_list(query_set):
        query_set = [i for i in query_set]
        result = [None]
        parent_idx_offset = 1
        while len(query_set) > 0:
            parent = result[-parent_idx_offset]
            for i in xrange(len(query_set)):
                if query_set[i].parent == parent:
                    result.append(query_set.pop(i))
                    parent_idx_offset = 1
                    break
            else:
                parent_idx_offset += 1
        result.pop(0)
        return result

    def get_queryset(self):
        query_set_all = super(CategoryManager, self).get_query_set()
        unordered_ids = [i.id for i in CategoryManager.generate_unordered_list(query_set_all)]
        clauses = ' '.join(['WHEN id=%s THEN %s' % (j, i) for i, j in enumerate(unordered_ids)])
        ordering = 'CASE %s END' % clauses

        return super(CategoryManager, self).get_query_set().extra(
            select={'ordering': ordering}, order_by=('ordering',)
        )


class Category(models.Model):
    
    parent = models.ForeignKey('self', blank=True, null=True, related_name='child')
    content = models.CharField(max_length=50)
    unique_together = ("parent", "content")

    objects = CategoryManager()

    @property
    def post_count(self):
        return self.post_set.count()

    @property
    def level(self):
        category_level = 0
        category_parent = self.parent
        while category_parent:
            category_level += 1
            category_parent = category_parent.parent
        return category_level

    def get_parents(self):
        path = [self]
        parent = self.parent
        while parent:
            path.insert(0, parent)
            parent = parent.parent
        return path

    @property
    def unordered_id(self):
        return list(Category.objects.all()).index(self)

    @property
    def enhanced_content(self):
        return ' --> '.join([i.content for i in self.get_parents()])

    def save(self, *args, **kwargs):
        if self.parent == self:
            raise ValueError("category can not be a parent of itself.")
        else:
            super(Category, self).save(*args, **kwargs)

    def __unicode__(self):
        return self.content


class Link(models.Model):
    
    name = models.CharField(unique=True, max_length=30)
    url = models.CharField(max_length=200)
    
    def __unicode__(self):
        return self.name


class UploadFile(models.Model):

    file = models.FileField(upload_to="%Y%m%d")
    description = models.CharField(max_length=30, blank=True, null=True)
    size = models.IntegerField()
    create_datetime = models.DateField(auto_now=True)

    def save(self, *args, **kwargs):
        self.size = self.file.size
        super(UploadFile, self).save(*args, **kwargs)

    @property
    def file_path(self):
        return self.file.name.split('/')[1]

    @property
    def url_path(self):
        from django.conf import settings
        return "%s%s" % (settings.MEDIA_URL, self.file.name)

    @property
    def size_human(self):
        k = self.size / 1024
        m = k / 1024
        if m != 0:
            return "%s MB" % round(float(self.size)/1024/1024, 2)
        elif k != 0:
            return "%s KB" % round(float(self.size)/1024, 2)
        else:
            return "%s B" % self.size

    def __unicode__(self):
        return self.file.name
